/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.q1cc.cfs.jamp.players;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
import net.q1cc.cfs.jamp.Main;
import net.q1cc.cfs.jamp.event.EventReporter;
import net.q1cc.cfs.jamp.event.JAmpSongEvent;
import net.q1cc.cfs.jamp.schema.Song;
import org.gstreamer.Bus;
import org.gstreamer.ClockTime;
import org.gstreamer.ElementFactory;
import org.gstreamer.Format;
import org.gstreamer.Gst;
import org.gstreamer.Message;
import org.gstreamer.Pipeline;
import org.gstreamer.State;
import org.gstreamer.elements.PlayBin2;

/**
 *
 * @author claus
 */
public class GStreamerHandler implements PlayerHandler {
    
    PlayBin2 playBin;
    Status status=Status.INIT;
    Song currentSong;
    
    public GStreamerHandler() {
        initPlayer();
    }
    
    public void destroy() {
        playBin.setState(State.NULL);
        status=Status.STOPPED;
        Gst.deinit();
    }

    public void initPlayer() {
        System.setProperty("jna.library.path", "C:\\Program Files (x86)\\OSSBuild\\GStreamer\\v0.10.6\\bin");
        System.out.println(System.getProperty("jna.library.path")+"    "+System.getProperty("java.class.path"));
        boolean error=false;
        try {
            Gst.init("JAmp",new String[0]);
        } catch (UnsatisfiedLinkError e) {
            e.printStackTrace();
            //Gst.init("JAmp",new String[0]);
        } catch(NoClassDefFoundError e){
            System.out.println(e.getCause());
            e.printStackTrace();
        }
        playBin=new PlayBin2("JAmp");
        playBin.setVideoSink(ElementFactory.make("fakesink","videosink")); //redirect video to /dev/null
        status=Status.STOPPED;
        
        //debug
        playBin.getBus().connect(new Bus.MESSAGE() {
            public void busMessage(Bus bus, Message message) {
                net.q1cc.cfs.jamp.Main.getInstance().miniPlayerGui.log(message.getType().getName()+": "+message.getStructure().toString());
            }
        });
        
    }

    public void play() {
        if(status==Status.STOPPED){
            playBin.setState(State.PLAYING);
            status=Status.STARTED;
            Main.getInstance().getEventReporter().throwEvent(new JAmpSongEvent("Song started", "", JAmpSongEvent.SONG_STARTED, currentSong));
            playBin.connect(new PlayBin2.ABOUT_TO_FINISH() {
                public void aboutToFinish(PlayBin2 element) {
                    status=Status.ENDED;
                    Main.getInstance().getEventReporter().throwEvent(new JAmpSongEvent("Song finished",null, JAmpSongEvent.SONG_ENDED, currentSong));
                }
            });
        }
    }

    public void playSong(Song song) {
        try {
            if(status==Status.STARTED || status==Status.PLAYING || status==Status.PAUSED){
                stop();
            }
            playBin.setState(State.NULL);
            URI uri=new URI(song.getValue("Location"));
            System.out.println("Playing "+uri);
            playBin.setURI(uri);
            currentSong=song;
            play();
        } catch (URISyntaxException ex) {
            ex.printStackTrace();
        }
    }

    public void playpause() {
        switch (status){
            case PLAYING:
            case STARTED:
                playBin.setState(State.PAUSED);
                status=Status.PAUSED;
                break;
            case PAUSED:
                playBin.setState(State.PLAYING);
                status=Status.STARTED;
                break;
            default:
                break;
        }
        
    }

    public void seek(long timeInMs) {
        System.out.println("total time in ms:"+playBin.queryDuration(TimeUnit.MILLISECONDS));
        playBin.seek(timeInMs, TimeUnit.MILLISECONDS);
    }
    public long getPosition(){
        return playBin.queryPosition().toMillis();
    }
    public long getDuration(){
        return playBin.queryDuration().toMillis();
    }

    public Status getStatus() {
        return status;
    }

    public void stop() {
        playBin.setState(State.PAUSED);
        playBin.seek(0,TimeUnit.MILLISECONDS);
        playBin.setState(State.READY);
        status=Status.STOPPED;
    }

    public void playFile(String file) {
        Song s=new Song();
        s.setValue("Location", file);
        playSong(s);
    }
    
}
